﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;

namespace XToolkit.Text
{
    public static class StringExtensions
    {
        /// <summary>
        /// 标准MD5加密
        /// </summary>
        /// <param name="text">要加密的字符串</param>
        /// <param name="upper">是否输出大写结果，默认为false</param>
        /// <returns></returns>
        public static string MD5(this string text, bool upper = false)
        {
            if (string.IsNullOrEmpty(text)) return string.Empty;

            MD5CryptoServiceProvider x = new MD5CryptoServiceProvider();
            byte[] bs = System.Text.Encoding.UTF8.GetBytes(text);
            bs = x.ComputeHash(bs);

            StringBuilder sb = new StringBuilder();
            string format = upper ? "X2" : "x2";
            foreach (byte b in bs)
            {
                sb.Append(b.ToString(format));
            }
            return sb.ToString();
        }

        /// <summary>
        /// 获取字符串的长度，汉字按2个字符计算
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        public static int GetGBLength(this string text)
        {
            if (string.IsNullOrEmpty(text))
            {
                return 0;
            }
            Encoding e = System.Text.Encoding.GetEncoding("GB18030");
            return e.GetByteCount(text);
        }


        /// <summary>
        /// 判断字符串是否为有效的email
        /// </summary>
        /// <param name="strIn"></param>
        /// <returns></returns>
        public static bool IsValidEmail(this string strIn)
        {
            if (string.IsNullOrEmpty(strIn))
            {
                return false;
            }
            // Return true if strIn is in valid e-mail format.
            string reg = @"^(?("")("".+?""@)|(([0-9a-zA-Z]((\.(?!\.))|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-zA-Z])@))(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,6}))$";
            //string reg = @"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$";
            return Regex.IsMatch(strIn, reg);
        }
        /// <summary>
        /// 验证字符串是否有效的中国身份证号码
        /// </summary>
        /// <param name="idcard">要验证的身份证号码</param>
        /// <returns></returns>
        public static bool IsValidChinaIdCard(this string idcard)
        {
            if (string.IsNullOrWhiteSpace(idcard))
            {
                return false;
            }
            var idcard_array = idcard.ToCharArray();
            string reg;
            switch (idcard.Length)
            {
                case 15:

                    if ((Convert.ToInt32(idcard.Substring(6, 2)) + 1900) % 4 == 0 || ((Convert.ToInt32(idcard.Substring(6, 2)) + 1900) % 100 == 0 && (Convert.ToInt32(idcard.Substring(6, 2)) + 1900) % 4 == 0))
                    {
                        reg = @"^[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}$"; //测试出生日期的合法性   
                    }
                    else
                    {
                        reg = @"^[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))[0-9]{3}$"; //测试出生日期的合法性   
                    }
                    if (Regex.IsMatch(idcard, reg))
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                case 18:
                    //18位身份号码检测   
                    //出生日期的合法性检查    
                    //闰年月日:((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))   
                    //平年月日:((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))   
                    if (Convert.ToInt32(idcard.Substring(6, 4)) % 4 == 0 || (Convert.ToInt32(idcard.Substring(6, 4)) % 100 == 0 && Convert.ToInt32(idcard.Substring(6, 4)) % 4 == 0))
                    {
                        reg = @"^[1-9][0-9]{5}19[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}[0-9Xx]$"; //闰年出生日期的合法性正则表达式   
                    }
                    else
                    {
                        reg = @"^[1-9][0-9]{5}19[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))[0-9]{3}[0-9Xx]$"; //平年出生日期的合法性正则表达式   
                    }
                    if (Regex.IsMatch(idcard, reg))
                    {//测试出生日期的合法性   
                        //计算校验位   

                        int S = (Convert.ToInt32(idcard_array[0].ToString()) + Convert.ToInt32(idcard_array[10].ToString())) * 7
                              + (Convert.ToInt32(idcard_array[1].ToString()) + Convert.ToInt32(idcard_array[11].ToString())) * 9
                              + (Convert.ToInt32(idcard_array[2].ToString()) + Convert.ToInt32(idcard_array[12].ToString())) * 10
                              + (Convert.ToInt32(idcard_array[3].ToString()) + Convert.ToInt32(idcard_array[13].ToString())) * 5
                              + (Convert.ToInt32(idcard_array[4].ToString()) + Convert.ToInt32(idcard_array[14].ToString())) * 8
                              + (Convert.ToInt32(idcard_array[5].ToString()) + Convert.ToInt32(idcard_array[15].ToString())) * 4
                              + (Convert.ToInt32(idcard_array[6].ToString()) + Convert.ToInt32(idcard_array[16].ToString())) * 2
                              + Convert.ToInt32(idcard_array[7].ToString()) * 1
                              + Convert.ToInt32(idcard_array[8].ToString()) * 6
                              + Convert.ToInt32(idcard_array[9].ToString()) * 3;
                        int Y = S % 11;
                        string M = "F";
                        string JYM = "10X98765432";
                        M = JYM.Substring(Y, 1); /*判断校验位*/
                        if (M == idcard_array[17].ToString().ToUpper())
                        {
                            return true;
                        }
                        else
                        {
                            return false;
                        }
                    }
                    else
                    {
                        return false;
                    }
                default:
                    return false;
            }
        }

    }
}
